<script setup lang="ts">
import { ref, unref, reactive, computed, defineAsyncComponent } from 'vue'
import { useBaseApi } from '@/api/base'
import { isArray, isNumber } from 'xe-utils'
import type { VxeGridProps, VxeTableInstance } from 'vxe-table'
import type {
  DicType,
  BusinessUIAction,
  BusinessUIFormType,
  BusinessUIQueryType,
  BusinessUITableType
} from '@/types/custom'
import {
  initFooterMethod,
  initFormatColumns,
  initGridProps,
  formatColRows
} from '@/views/components/grid/libs'
import { storeToRefs } from 'pinia'
import { useAppState } from '@/stores/appState'
import { Delete, EditPen } from '@element-plus/icons-vue'

const TemplateQuery = defineAsyncComponent(
  () => import('@/views/components/form/TemplateQuery.vue')
)

const { CustomRequest, get_business_ui } = useBaseApi()
const { mobile } = storeToRefs(useAppState())

interface Props {
  multiple?: boolean
  business_id?: string
}

const props = defineProps<Props>()

const modelValue = defineModel<string | string[] | undefined>()

const emit = defineEmits(['close', 'fetch', 'confirm'])

// 表格
const modal = ref(false)
const xGrid = ref<VxeTableInstance>()
const loading = ref(false)
const params = ref<TypedAny>({})
const gridOptions = ref<VxeGridProps<TypedAny>>({})
// 表格
const uiTable = ref<BusinessUITableType | undefined>()
// 表格
const uiForm = ref<BusinessUIFormType | undefined>()
// 查询栏
const uiQuery = ref<BusinessUIQueryType | undefined>()
// 表单字典
const dicTable = ref<DicType[]>([])
// 查询字典
const dicQuery = ref<DicType[]>([])
// 按钮配置
const uiActions = ref<BusinessUIAction[]>([])
// 表格分页
const gridPage = reactive({
  total: 0,
  page: 1,
  pageSize: 50
})
const current = ref('select')
const options = [
  { label: '全部', value: 'select' },
  { label: '已选', value: 'selected' }
]
const items = ref<TypedAny[]>([])
const checkbox = ref<TypedAny[]>([])
const radio = ref<string>()

const gridData = computed(() => {
  if (current.value === 'selected') {
    return checkbox.value
  } else {
    return items.value
  }
})

// 主键
const keyField = computed(() => uiTable.value?.default_value_parse.keyField || 'id')

/**
 * 获取业务详情
 */
const onFetchBusiness = async () => {
  loading.value = true
  if (!props.business_id) return Promise.reject(false)
  const { data } = await get_business_ui(props.business_id)

  if (!data.ui_table) return Promise.reject(false)

  uiTable.value = data.ui_table
  uiQuery.value = data.ui_query
  uiForm.value = data.ui_form
  dicTable.value = data.dic_table || []
  dicQuery.value = data.dic_query || []
  uiActions.value = data.actions || []

  // 加载数据
  // await onFetch()

  // 格式化表格配置
  gridOptions.value = initGridProps({
    uiTable: data.ui_table,
    radioConfig: {
      trigger: 'row',
      reserve: true,
      highlight: true
    }
  })

  const cols = await initFormatColumns({
    uiForm: data.ui_form,
    uiTable: data.ui_table,
    dicTable: data.dic_table,
    uiActions: data.actions
  })

  // 初始化表尾合计
  initFooterMethod(unref(gridOptions), cols)

  gridOptions.value.columns = [
    {
      type: props.multiple ? 'checkbox' : 'radio',
      width: 40
    },
    ...cols.filter((f) => f.field !== 'action')
  ]

  loading.value = false
}

/**
 * 查询数据
 * @param slotParams 查询参数
 */
const onFetch = async (slotParams?: TypedAny) => {
  const table = unref(uiTable)
  if (!table) return Promise.reject(false)

  loading.value = true

  const param = Object.assign({}, gridPage, slotParams, unref(params))

  const { data } = await CustomRequest<{ items: TypedAny[]; total: number }>({
    url: table.api,
    method: table.method,
    params: table.method === 'get' ? param : unref(params),
    data: table.method === 'post' ? param : undefined
  })

  // 总数
  if (data && isNumber(data.total)) gridPage.total = data.total

  let list: TypedAny[] = []
  if (isArray(data)) {
    list = data
  } else if (data.items) {
    list = data.items
  }

  formatColRows({
    rows: list,
    uiTable: uiTable.value,
    uiForm: uiForm.value,
    dicTable: dicTable.value
  })

  items.value = list

  // if (!selected.value.length) selected.value = data.selected || []

  // 赋值选中
  setRadioChange()

  loading.value = false
}

const getLabel = (option: SelectOptionType) => {
  return option.value === 'selected'
    ? `${option.label}（${checkbox.value.length}）`
    : `${option.label}（${gridPage.total}）`
}

const onCheckboxChange = () => {
  const key = unref(keyField)
  const $grid = xGrid.value
  if (!$grid) return
  const records = $grid.getCheckboxRecords(true)
  const list = unref(checkbox)
  if (current.value === 'selected') {
    checkbox.value = list.filter((f) => records.some((s) => s[key] === f[key]))
  } else {
    const nots = list.filter((f) => !items.value.some((s) => s[key] === f[key]))
    checkbox.value = [...records, ...nots]
  }
}

const onRadioChange = () => {
  const $grid = xGrid.value
  if (!$grid) return
  const row = $grid.getRadioRecord()
  if (row) radio.value = row[unref(keyField)]
}

const handleClear = () => {
  const $grid = xGrid.value

  if (props.multiple) {
    checkbox.value = []
    if ($grid) $grid.clearCheckboxRow()
  } else {
    radio.value = undefined
    if ($grid) $grid.clearRadioRow()
  }
}

/**
 * 保存
 */
const onSave = async () => {
  if (props.multiple) {
    emit(
      'confirm',
      checkbox.value.map((v) => v[unref(keyField)])
    )
  } else {
    emit('confirm', radio.value)
  }
  modal.value = false
}

const setRadioChange = () => {
  setTimeout(() => {
    // 赋值选中
    const $grid = xGrid.value
    if ($grid) {
      if (props.multiple) {
        $grid.setCheckboxRow(checkbox.value, true)
      } else {
        $grid.setRadioRow(radio.value)
      }
    }
  }, 150)
}

const onAction = () => {}

// const onRefresh = () => {
//   selected.value = props.multiple ? [] : {}
//   onFetch()
// }

const open = async () => {
  await onFetchBusiness()
  modal.value = true
}

defineExpose({ open, handleClear })
</script>

<template>
  <vxe-modal
    show-zoom
    :show-minimize="false"
    :dblclick-zoom="false"
    resize
    v-model="modal"
    width="80%"
    height="80%"
    destroy-on-close
    class-name="custom-modal"
  >
    <template #title>
      <el-space :size="5">
        <el-radio-group v-if="multiple" v-model="current" @change="setRadioChange">
          <el-radio-button
            v-for="(option, index) in options"
            :key="index"
            :value="option.value"
            :label="getLabel(option)"
          />
        </el-radio-group>
        <el-button :icon="Delete" type="danger" @click="handleClear">清空</el-button>
        <el-button :icon="EditPen" type="success" @click="onSave">确认</el-button>
      </el-space>
    </template>
    <div class="h100 flex flex-column">
      <TemplateQuery
        v-if="uiTable"
        :value="true"
        ref="queryRef"
        :ui-query="uiQuery"
        :ui-actions="uiActions"
        :dic-query="dicQuery"
        :right-spacing="0"
        @action="onAction"
        @fetch="onFetch"
      />
      <div class="flex-grow relative">
        <vxe-grid
          ref="xGrid"
          v-bind="gridOptions"
          height="auto"
          :data="gridData"
          :loading="loading"
          append-to-body
          class="table-grid"
          @radio-change="onRadioChange"
          @checkbox-change="onCheckboxChange"
          @checkbox-all="onCheckboxChange"
        >
          <!-- 标签 -->
          <template #el_tag="{ row, column }">
            <el-tag :type="row[`${column.field}_display_type`] || 'info'">
              {{ row[column.field] }}
            </el-tag>
          </template>
          <!-- pager 插槽-->
          <template #pager v-if="uiTable?.pagination && current === 'select'">
            <vxe-pager
              :layouts="
                mobile
                  ? ['PrevJump', 'PrevPage', 'Number', 'NextPage', 'Total']
                  : [
                      'Sizes',
                      'PrevJump',
                      'PrevPage',
                      'Number',
                      'NextPage',
                      'NextJump',
                      'FullJump',
                      'Total'
                    ]
              "
              v-model:current-page="gridPage.page"
              v-model:page-size="gridPage.pageSize"
              :total="gridPage.total"
              @page-change="onFetch()"
            >
            </vxe-pager>
          </template>
        </vxe-grid>
      </div>
    </div>
  </vxe-modal>
</template>
<style lang="scss" scoped>
.table-grid {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}
</style>
